
#pragma once
#include<iostream>
#include<string>
#include<sys/types.h>
#include<sys/socket.h>
#include<cstring>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<unistd.h>

#define DEFAULT 8081


class UdpServer{

private:
	std::string ip;
	int port;
	int sockfd;

public:
	UdpServer(std::string _ip ,int _port = DEFAULT ):port(_port),sockfd(-1),ip(_ip)
	{
	
	}
// !!!!!!!!!
	bool InitUdpServer()
	{

		sockfd = socket(AF_INET, SOCK_DGRAM,0);
		if(sockfd < 0){
			std::cerr << "socket error" << std::endl;
			return false;
		}
		std::cout << "socket create success, sockfd: " << sockfd << std::endl;
	
		// 此处为绑定做初始准备，创建变量和清零	
		struct sockaddr_in local;
		memset(&local, '\0', sizeof(local));
		
		local.sin_family = AF_INET;
		local.sin_port = htons(port);

		// 这里传入ip ，我们拥有字符串形式的ip，但是它需要整数形式，于是我们使用系统提供的库函数来完成转换,即 inet_addr（） 这是C语言形式的接口
		local.sin_addr.s_addr = inet_addr(ip.c_str());

		// 正式开始绑定
		if(bind(sockfd, (struct sockaddr*)& local ,sizeof(local)) < 0 ){
			std::cerr << "bind error" << std::endl;
			return false;
		}	

		std::cout << "bind success, sockfd" << sockfd << std::endl;
		
		return true;
	}
// !!!!!!!!!!!
	void Start()
	{
		#define SIZE 128
		char buffer[SIZE] = {0};
		for(;;)
		{
			struct sockaddr_in peer;
			socklen_t len = sizeof(peer);
			ssize_t size = recvfrom(sockfd, buffer, sizeof(buffer)-1,0,(struct sockaddr *) &peer ,&len);
	// 此处强制类型转换通不过，我很疑惑
			if(size > 0){
				buffer[SIZE] = 0;
				// 这里也有一个转换的过程 , 本地的端口号需要的是整数
				int _port = ntohs(peer.sin_port);
				std::string _ip = inet_ntoa(peer.sin_addr);
				std::cout<< _ip <<":" << _port << "# "<< buffer<<std::endl;
				
			}
			else{
				std::cerr << "recvfrom error " << std::endl;
			}

		}	

	}
	~UdpServer()
	{}

};






